<!-- 菜单信息 -->
<template>
  <div class="">
    <el-row :gutter="10">
      <el-col :span="6">
        <el-card class="box-card">
          <el-input placeholder="输入关键字进行过滤" v-model.trim="filterText">
          </el-input>
          <el-tree class="filter-tree" :load="loadNode" :props="defaultProps" :filter-node-method="filterNode"
            :expand-on-click-node="false" :current-node-key="currentNodeKey" node-key="id"
            :default-expanded-keys="state.defaultExpandedKeys" highlight-current lazy @node-click="handleNodeClick"
            ref="treeRef">
            <template #default="{ node, data }">
              <span class="custom-tree-node">
                <span>{{ node.label }}</span>
                <span>
                  <el-button type="primary" text size="small" v-if="node.level !== 5"
                    @click.stop="e => handleAppend(node, data, e)">
                    新增
                  </el-button>
                  <el-button text size="small" class="red ml0" v-if="node.level !== 1"
                    @click.stop="e => handleRemove(node, data, e)">
                    删除
                  </el-button>
                </span>
              </span>
            </template>
          </el-tree>
        </el-card>
      </el-col>
      <el-col :span="18">
        <el-card class="box-card">
          <el-form label-width="120px" :model="menuForm" :rules="rules" :highlight-current="true"
            v-loading="loadingDialog" ref="menuFormRef">
            <el-row :gutter="10">
              <el-col :span="10">
                <el-form-item label="菜单类型：" prop="type">
                  <el-radio-group v-model="menuForm.type" @change="handleChangeMenuType">
                    <el-radio :label="1">目录</el-radio>
                    <el-radio :label="2">菜单</el-radio>
                    <el-radio :label="3">权限</el-radio>
                  </el-radio-group>
                </el-form-item>
              </el-col>
            </el-row>
            <el-row :gutter="10">
              <el-col :span="7">
                <el-form-item label="标题：" prop="title">
                  <el-input v-model.trim="menuForm.title" placeholder="点击新增后添加标题"></el-input>
                </el-form-item>
              </el-col>
              <el-col :span="7">
                <el-form-item label="路由：" prop="path">
                  <el-input v-model.trim="menuForm.path"></el-input>
                </el-form-item>
              </el-col>
              <el-col :span="1" v-if="menuForm.type === 1">
                <el-tooltip placement="top" content="目前可随意填写地址,不重复即可（如：1）">
                  <el-icon class="icon-wzg-config">
                    <InfoFilled />
                  </el-icon>
                </el-tooltip>
                <el-col :span="1">
                </el-col>
              </el-col>
              <el-col :span="1" v-if="menuForm.type === 2">
                <el-tooltip placement="top" content="前端页面访问的地址（如：/menuInfo）">
                  <el-icon class="icon-wzg-config">
                    <InfoFilled />
                  </el-icon>
                </el-tooltip>
              </el-col>
              <el-col :span="1" v-if="menuForm.type === 3">
                <el-tooltip placement="top" content="后端接口的地址（如：back/auth）">
                  <el-icon class="icon-wzg-config">
                    <InfoFilled />
                  </el-icon>
                </el-tooltip>
              </el-col>
            </el-row>
            <el-row :gutter="10" v-if="menuForm.type === 3">
              <el-col :span="7">
                <el-form-item label="请求方式：" prop="method">
                  <el-select v-model.trim="menuForm.method" placeholder="请选择状态" clearable class="">
                    <el-option v-for="item in state.selectRequestMethodList" :label="item.dictLabel"
                      :value="item.dictValue" :key="item.id"></el-option>
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :span="7">
                <el-form-item label="动作：" prop="action">
                  <el-input v-model.trim="menuForm.action"></el-input>
                </el-form-item>
              </el-col>
              <el-col :span="1">
                <el-tooltip placement="top" content="按钮对应权限的名称(如：新增:add;编辑:edit)">
                  <el-icon class="icon-wzg-config">
                    <InfoFilled />
                  </el-icon>
                </el-tooltip>
              </el-col>
            </el-row>
            <el-row :gutter="10" v-if="menuForm.type !== 3">
              <el-col :span="7" v-if="menuForm.type === 2">
                <el-form-item label="模块名称：" prop="name">
                  <el-input v-model.trim="menuForm.name"></el-input>
                </el-form-item>
              </el-col>
              <el-col :span="7" v-if="menuForm.type === 1">
                <el-form-item label="权重：" prop="sort">
                  <el-input v-model.trim="menuForm.sort"></el-input>
                </el-form-item>
              </el-col>
              <el-col :span="7" v-if="menuForm.type !== 3">
                <el-form-item label="图标：" prop="icon">
                  <el-input v-model.trim="menuForm.icon"></el-input>
                </el-form-item>
              </el-col>
              <el-col :span="1" v-if="menuForm.type === 2">
                <el-tooltip placement="top" content=" 一级为菜单时需要添加图标">
                  <el-icon class="icon-wzg-config">
                    <InfoFilled />
                  </el-icon>
                </el-tooltip>
              </el-col>
            </el-row>
            <el-row :gutter="10" v-if="menuForm.type === 2">
              <el-col :span="7">
                <el-form-item label="权重：" prop="sort">
                  <el-input v-model.trim="menuForm.sort"></el-input>
                </el-form-item>
              </el-col>
            </el-row>
          </el-form>
          <el-row :gutter="10">
            <el-col :span="6" :offset="1">
              <el-button type="primary" :icon="Check" :disabled="disabledbtn"
                @click="submitForm(menuFormRef, menuForm, methodType, 'commonMenuInfo', 'getMenuInfo')">保存</el-button>
              <!-- <el-button type="success"
                         icon="el-icon-refresh"
                         :disabled="disabledbtn"
                         @click="getMenuInfo">刷新</el-button> -->
            </el-col>
          </el-row>
          <el-row :gutter="10">
            <el-col :span="20" :offset="1">
              <ul>
                <li>菜单只有一级的时候，路由写真实路由，二级的时候，路由只要不重复即可，数字即可</li>
                <li>图标的获取地址：https://element-plus.gitee.io/zh-CN/component/icon.html</li>
              </ul>
            </el-col>
          </el-row>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script setup>
import { reactive, ref, nextTick, watch } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { View, Search, Refresh, Check } from '@element-plus/icons-vue';
import { common as Common } from '@/utils/common.js';
import { api as Request, imageUrl, uploadUrl } from '@/utils/api';
import { useDialogForm } from '@/hooks/useDialogForm.js';
import { useDictData } from '@/hooks/network/useDictData.js';

const state = reactive({
  selectRequestMethodList: [],/* 请求方式 */
  menuData: [],
  defaultExpandedKeys: [0]/* 默认显示哪几级信息 */
});
let { getDictDataInfo } = useDictData();
const filterText = ref('');
const treeRef = ref('');
const menuFormRef = ref('');
const defaultProps = reactive({
  children: 'children',
  label: 'title'
})
const currentNodeKey = ref('');/* 当前选中的节点 */
const searchCondition = reactive({
  p_id: 0
})
const methodType = ref('POST');/* 请求类型 */

const menuForm = reactive({
  id: '',
  p_id: 0,
  type: 1,
  icon: '',
  title: '',
  path: '',
  name: '',
  method: '',
  action: '',
  sort: 0
})
let rules = reactive({});
/* 目录规则 */
const contentRules = {
  title: [{ required: true, message: '请填写标题', trigger: 'blur' }],
  path: [{ required: true, message: '请填写路由', trigger: 'blur' }],
  sort: [{ required: true, message: '请填写权重', trigger: 'blur' }]
};

/* 菜单规则 */
const menuRules = {
  title: [{ required: true, message: '请填写标题', trigger: 'blur' }],
  name: [{ required: true, message: '请填写模块名称', trigger: 'blur' }],
  path: [{ required: true, message: '请填写路由', trigger: 'blur' }],
  sort: [{ required: true, message: '请填写权重', trigger: 'blur' }]
}
/* 按钮规则 */
const buttonRules = {
  title: [{ required: true, message: '请填写标题', trigger: 'blur' }],
  path: [{ required: true, message: '请填写路由', trigger: 'blur' }],
  method: [
    { required: true, message: '请选择请求方式', trigger: 'blur' }
  ],
  action: [{ required: true, message: '请填写行为', trigger: 'blur' }]
}
const delVisibleType = ref('delete');/* 删除类型（单选，多选） */
const loadingDialog = ref(false);/* */
const disabledbtn = ref(false); /* 可用与不可用 */
const node = ref(''); /* 删除时的节点与节点数据 */
const node_had = ref('');/* */
const isParent = ref(true);/* */
const id = ref('');/* */

/* 过滤节点信息 */
const filterNode = (value, data) => {
  if (!value) return true;
  return data.title.indexOf(value) !== -1;
}
/* 更新tree中某个结点 */
const handleUpdateTree = () => {
  // 通过ID利用DOM找到该结点
  const node = treeRef.value.getNode(node_had.value);
  const tempNode = isParent.value ? node.parent : node;
  // 更改该结点属性
  tempNode.loaded = false;
  // 手动调用该结点数据加载方法
  tempNode.loadData();
}

/* 点击获取节点信息 */
const handleNodeClick = (data, _node) => {
  node_had.value = _node;
  if (node.level === 1) return;
  isParent.value = true;

  menuForm.id = data.id;
  menuForm.title = data.title;
  menuForm.p_id = _node.parent.data.id;
  if (menuForm.p_id == undefined) {
    menuForm.p_id = 0;
  }
  if (data.id !== '') {
    /* 修改 */
    methodType.value = 'PUT';

    menuForm.path = data.path;
    menuForm.icon = data.icon;
    menuForm.sort = data.sort;
    menuForm.name = data.name;
    menuForm.action = data.action;
    menuForm.method = data.method;

    /* 判断是 目录，菜单，按钮 */
    handleJudgeMenuType();
  } else {
    /* 新增 */
    methodType.value = 'POST';

    menuForm.type = 1;
    menuForm.path = '';
    menuForm.method = '';
    menuForm.action = '';
    menuForm.icon = '';
    menuForm.sort = '';
    menuForm.name = '';
  }
}
/* 数据初始化 */
const handleInitData = () => {
  methodType.value = 'POST';
  menuForm.title = '';
  menuForm.p_id = '';
  menuForm.type = 1;
  menuForm.path = '';
  menuForm.method = '';
  menuForm.action = '';
  menuForm.icon = '';
  menuForm.sort = 0;
  menuForm.name = '';
}
/* 判断是 目录，菜单，按钮 */
const handleJudgeMenuType = () => {
  if (menuForm.name !== '') {
    menuForm.type = 2;
    rules = menuRules;
    return;
  }
  if (menuForm.action !== '') {
    menuForm.type = 3;
    rules = buttonRules;
    return;
  }
  /* 默认目录 */
  menuForm.type = 1;
  rules = contentRules;
}
/* 添加节点 */
const handleAppend = (node, data, e) => {
  if (!node.loaded) {
    ElMessage.warning(`请先点击左侧小箭头，加载下级，再进行新增下级操作`);
    return;
  }
  e.stopPropagation();
  isParent.value = false;
  const childNodes = node.childNodes;
  for (let i = 0; i < childNodes.length; i++) {
    if (childNodes[i].data.id === '') return;
  }
  const newChild = {
    id: '',
    title: '',
    children: []
  };

  if (!data.children) {
    data.children = []
  }
  data.children.push(newChild);

  node_had.value = node;
  handleInitData();
  menuForm.p_id = node.data.id;
}
/* 删除节点 */
const handleRemove = (node, data, e) => {
  isParent.value = true;
  e.stopPropagation();
  if (data.id === '') {
    const parent = node.parent;
    const children = parent.data.children || parent.data;
    const index = children.findIndex((d) => d.id === data.id);
    children.splice(index, 1);
    node.parent.loaded = false;
    node.parent.loadData();
    handleInitData();
  } else {
    id.value = data.id;
    /* 发送请求id 去删除数据 */
    delVisibleType.value = 'delete';
    node_had.value = node;
    deleteMessageBox('deleteMenuInfo');
  }
}
/* 切换菜单类型 */
const handleChangeMenuType = (data) => {
  menuFormRef.value.resetFields();
  menuForm.type = data;
  if (data === 1) {
    rules = contentRules;
    menuForm.method = '';
    menuForm.action = '';
    menuForm.name = '';
  } else if (data === 2) {
    rules = menuRules;
    menuForm.method = '';
    menuForm.action = '';
  } else if (data === 3) {
    rules = buttonRules;
    menuForm.icon = '';
    menuForm.name = '';
  }
}
/* 请求：获取菜单信息 */
const getMenuInfo = () => {
  disabledbtn.value = true;
  Request.getMenuInfo(searchCondition)
    .then((res) => {
      if (res.status === 1 && res.result.length !== 0) {
        state.menuData[0].children = res.result;
      }
    })
    .catch((res) => { }).finally(() => { disabledbtn.value = false; });
}
/* 加载节点数据 */
const loadNode = async (node, resolve) => {
  node_had.value = node;
  if (node.level === 0) {
    const data = {
      id: 0,
      title: '菜单信息管理',
      children: []
    };
    state.menuData.push(data);
    return resolve([data]);
  }
  if (node.data.id === '') return resolve([]);
  try {
    searchCondition.p_id = node.data.id;
    const res = await Request.getMenuInfo(searchCondition);
    if (res.status === 1 && res.result.length !== 0) {
      return resolve(res.result);
    }
    return resolve([]);
  } catch (error) {
    console.log(error);
    return resolve([]);
  }
}
/* 保存或编辑 */
const submitForm = (formEl, formData, type, method, refreshMethod) => {
  if (isParent.value && node_had.data && node_had.data.id === 0) {
    ElMessage.warning(`'菜单信息管理'目录不能修改`);
    return;
  }
  formEl.validate((valid) => {
    if (valid) {
      submitFormInfo(formData, type, method, refreshMethod);
    } else {
      /* 提示还有需要填写的信息 */
      ElMessage.warning('请填写所有必填信息');
      return false;
    }
  });
}
/* 保存或编辑信息 */
const submitFormInfo = (formData, type, method, refreshMethod) => {
  /* 防止多次提交 */
  disabledbtn.value = true;
  loadingDialog.value = true;
  Request[method](formData, type)
    .then((res) => {

      ElMessage.success(res.msg);
      /* 重新刷新数据 */
      // this[refreshMethod]();
      handleUpdateTree();
      handleInitData();
    })
    .catch((res) => { }).finally(() => {
      disabledbtn.value = false;
      loadingDialog.value = false;
    });
}
/* 打开删除弹框 */
const deleteMessageBox = (method) => {
  ElMessageBox.confirm('删除不可恢复，是否确定删除?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  })
    .then(() => {
      deleteInfo({ idArray: id.value }, method);
    })
    .catch(() => {
      ElMessage.info('已取消删除');
    });
}

/* 删除后的信息 */
const deleteInfo = (data, method) => {
  disabledbtn.value = true;
  Request[method](data)
    .then((res) => {
      handleUpdateTree();
      handleInitData();
      ElMessage.success(`删除数据成功`);
    })
    .catch((res) => { }).finally(() => { disabledbtn.value = false; });
}

/* 监听筛选数据 */
watch(filterText, (val) => {
  treeRef.value.filter(val)
})
rules = contentRules;
/* 获取请求方式 */
getDictDataInfo('REQUEST_METHOD', state, 'selectRequestMethodList');
</script>

<style scoped>
.el-row {
  margin-bottom: 15px;
}

.el-col {
  border-radius: 4px;
}

.bg-purple-dark {
  background: #99a9bf;
}

.bg-purple {
  background: #d3dce6;
}

.bg-purple-light {
  background: #e5e9f2;
}

.grid-content {
  border-radius: 4px;
  min-height: 36px;
}

.row-bg {
  padding: 10px 0;
  background-color: #f9fafc;
}

.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}

/* 提示图标设置 */
.icon-wzg-config {
  height: 30px;
  line-height: 30px;
}

.el-tree {
  height: 740px;
  overflow: scroll;
}

.red {
  color: #f00;
}

/* 修改select的盒模型 */
.el-select {
  display: block;
}

:deep(.el-tree-node__label) {
  width: 100%
}

.ml0 {
  margin-left: 0;
}
</style>
